home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / misc / softboot331.lha / softboot3.31 / SoftBoot.c < prev    next >
C/C++ Source or Header  |  1992-11-09  |  34KB  |  976 lines

  1. /*
  2.     SoftBoot V3.31 for any A3000/68030 or 68040 system; Tested OK
  3.         if run in startup-sequence on an A4000.
  4.  
  5.         by Greg Tibbs 10/25/1992 ; some code from  SetCPU V1.4 by Dave Haynie
  6.  
  7.     MAIN PROGRAM
  8.  
  9.         Assumptions: The 040 for the A3000 only works under 2.0+, so there are
  10.                      assumptions that exec knows about an 040, that ROMsize
  11.                      is 512K. ZorroIII space is automatically found and MMU
  12.                      tables allocated and initialized. ZorroII caching
  13.                      defaults to on unless explicitly turned off or a
  14.                      BridgeBoard is found in the system. Compiled using
  15.                      SAS/C V6.00. Assembly module SofTag.asm must be
  16.                      linked in. The Assembly module has the magic to
  17.                      perform reboot recovery as well as talk to the 030
  18.                      and 040 MMUs directly.
  19.  
  20. */
  21.  
  22. #define PROGRAM_VERSION "V3.31"
  23.  
  24. #include <exec/types.h>
  25. #include <exec/execbase.h>
  26. #include <exec/memory.h>
  27. #include <libraries/configvars.h>
  28. #include <proto/all.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <fcntl.h>
  33.  
  34. #include "proto.h"
  35.  
  36. #define ROUND030        0x00008000L
  37. #define ROUND           0x00002000L
  38. #define ROMSIZE         0x00080000L
  39. #define BONUSSIZE1_3    0x00045000L
  40. #define FASTROMLOC      0x07f80000L
  41. #define BASEROMLOC      0x00f80000L
  42. #define TABSIZE         (128L * sizeof(ULONG))
  43. #define LEV3TABSIZE     0x2000L
  44. #define Z3STARTADDR     0x10000000L
  45. #define Z3ENDADDR       0xffffffffL
  46. #define WALL            0x100L
  47. #define WALLSIZE        2*WALL
  48. #define PFLUSHA040      0xf518
  49. #define CINVA040        0xf4d8
  50. #define MOVEC           0x4e7b
  51. #define NOP             0x4e71
  52. #define TCMASK030       0x80000000L
  53. #define FASTROMADDRMASK 0x7000000L
  54. #define MMU030TABLESIZE 0x8000L
  55. #define Z3L3SIZEPERBLOCK 0x4000L
  56. #define Z3L2SIZEPERBLOCK 0X200L
  57. #define PAGESIZE030     0X80000L
  58. #define PDTRESIDENT     0x01L
  59. #define UDTRESIDENT     0x03L
  60. #define CM_GLOBAL       0x400L
  61. #define WR_PROTECT      0x04L
  62. #define CM_COPYBACK     0x020L
  63. #define CM_INH_SER      0x040L
  64. #define CM_INH_NONSER   0x060L
  65. #define L1MASK         ~0x1ffL  /* Masks used in MMU table addresses for Level 1, 2 & 3 tables */
  66. #define L2MASK         ~0x7fL
  67. #define L3MASK         ~0x1fffL
  68.  
  69. int CXBRK(void) {return(0L);}
  70.  
  71. /* External Variables */
  72.  
  73. extern struct ExecBase *SysBase;
  74.  
  75. /* Communication to the assembly module is via common
  76.    memory areas, rather than passing the data on the stack or via
  77.    a register. */
  78.  
  79. __far extern ULONG PhyRomStart, LogRomStart, SRP, CRP0;
  80. __far extern ULONG CRP1, TC030;
  81. __far extern ULONG StartRom, BusErr, CatchRom, Z3cache;
  82. __far extern ULONG TC, MemListArray[24], NumMemAreas;
  83. __far extern ULONG GetTC030(void), GetTC040(void),  GetCPUType(void);
  84. __far extern void  MyColdReboot(void), JTRom(void), SpeedRom(void), MakeRomTag(void);
  85. __far extern void  JTRom13030(void), MakeRomTag13(void), ForceTTX(void);
  86. __far extern void  KillRomTags(void), SF_Supervisor(void), CachesOff(void);
  87.  
  88. struct ConfigureIt 
  89. {
  90.   ULONG StartAddr;
  91.   ULONG EndAddr;
  92.   ULONG BridgeBoard;
  93. };
  94.  
  95. /* WallFreemem must be used to  return all WALLed memory allocations */
  96.  
  97. void WallFreeMem( void *Address, ULONG size)
  98. {
  99.   Address=(void *)((ULONG)Address-WALL);
  100.   size += WALLSIZE;
  101.   FreeMem(Address,size);
  102. }
  103.  
  104. /* KillRomTags() is an assembly function to overwrite the ID so leftover
  105.    copies of the romtags embedded in this executable won't accidentially get 
  106.    found and run on reboot. Fastrom in particular was dangerous as if
  107.    the romtag was found in RAM which was loaded during the fastrom operation,
  108.    the MMU might get setup with a working MMU environment which would get
  109.    stomped on as soon as any program overwrites that area as the MMU memory 
  110.    areas would not be autoallocated and protected. The Ram occupied by the 
  111.    romtag would not be protected either, BTW.
  112.  
  113.    A Real RomTag is only made when it is intended to softload a new 
  114.    operating system. Currently, the romtag must be in a list in ExecBase, 
  115.    or in special areas of ram to be autodetected, but the romtag IDs are
  116.    obliterated just in case of future OS change where other areas may
  117.    be autodetected. In any situation that exit() is to be called, we are 
  118.    going to return to the OS, and not softload, so the IDs are overwritten 
  119.    to be safe. */
  120.  
  121. void exit2(ULONG error)
  122. {
  123.    KillRomTags();
  124.    exit(error);
  125. }
  126.  
  127. /* MyExit returns RAM allocated for the ROM before exiting */
  128.  
  129. void MyExit(error,TempROM)
  130. ULONG error, *TempROM;
  131. {
  132.   if((ULONG)TempROM==FASTROMLOC)
  133.   {
  134.     FreeMem((ULONG *)FASTROMLOC,ROMSIZE);
  135.   }
  136.   else
  137.   {
  138.     if(TempROM) WallFreeMem(TempROM,ROMSIZE);
  139.   }
  140.   exit2(error);
  141. }
  142.  
  143. /* TableFill13 build 68040 MMU tables for a 1.3 Bonus kickstart image.
  144.    This improved version writes the 040 MMU tables into the temporary
  145.    ram covered by the 1.3 rom image, rather than at the final address (unless
  146.    they coinside).    This allows me to delay Disable()ing the system until 
  147.    much later, and to not corrupt any possible previous rom or data at 
  148.    7f80000-7ffffff until I am very close to rebooting. */
  149.  
  150. void TableFill13(TempROM, cache)
  151. ULONG *TempROM, cache;
  152. {
  153.    ULONG *TempTable, PageField;
  154.    int i;
  155. /*
  156.    The 1.3 bonus is very sneaky. It is setup with built-in 030 MMU tables,
  157.    and code to add the motherboard fast ram, read the real time clock and
  158.    to start the hard drives. The 1.3 ROM and Bonus is more than 256K but
  159.    less than 512K. There is plenty of room to add 68040 MMU tables as well.
  160.    The area from 7f80000 to 7fbffff is standard 256K 1.3 kickstart. MMU tables
  161.    map, or mirror that to f80000 to fbffff and to fc0000 to ffffff, to make 
  162.    it look like a standard ROM system. The area in 7fc0000 to 7ffffff is 
  163.    mapped to  f00000 to f7ffff. 1.3 Kickstart will read this area for any 
  164.    romtags; they do not have to be linked into any system list as with other 
  165.    locations. In the mirror is a romtag which initializes the clock, ram, and 
  166.    hard drive. In the assembly module, I built my own romtag, which
  167.    SetFunction()s ColdCapture(). 2.0 and later exec honors the 1.3 execbase
  168.    structure and will run the 1.3 execbase ColdCapture() vector before it 
  169.    realizes that it is not a 2.0+ execbase and relocates it. My Romtag
  170.    then reloads the MMU and jumps back into 1.3, providing hardware
  171.    (Keyboard) reboot recovery. Obviously anything which overwrites
  172.    ColdCapture() without chaining it will cause the hardware reboot 
  173.    recovery process to fail. As a result, I blast my vector in (I do not
  174.    chain) each time the romtag is run.
  175. */
  176.    /* Calculate Pointer to 1st level MMU table in temporary RAM */
  177.  
  178.    TempTable = (ULONG *)(0x46000L + (ULONG)TempROM);
  179.  
  180.    /*Fill 1st level table */
  181.  
  182.    for (i = 1; i < 128; i++) *(TempTable+i) = 0L;
  183.  
  184.    /* Point entry for lowest 32 Meg block to 2nd level table */
  185.  
  186.    *TempTable = ((0x7fc8000L & L1MASK) | UDTRESIDENT); /* Point to Level 2 Table */
  187.  
  188.    /* Calculate 2nd Level table location in temporary ROM space */
  189.  
  190.    TempTable = (ULONG *)(0x48000L + (ULONG)TempROM);
  191.  
  192.    /* Fill in 2nd level table with pointers to 3rd level table */
  193.  
  194.    for (i=64; i<128; i++) *(TempTable+i)=0L;
  195.    for (i=0; i<64; i++)
  196.          *(TempTable+i)=(((0x7fca000L+i*128) & L2MASK) | UDTRESIDENT);
  197.  
  198.    /* Calculate 3rd level table address */
  199.  
  200.    TempTable = (ULONG *)(0x4a000L + (ULONG)TempROM);
  201.  
  202.    /* Fill in 3rd level table for lowest 15 Meg */
  203.  
  204.    PageField = CM_GLOBAL | CM_INH_SER | PDTRESIDENT;
  205.    for (i=0; i<1984; i++) /*Romaddr/pagesize = 0xf80000/0x2000 = 1984 pages*/
  206.       *(TempTable+i) = (((8192L*i) & L3MASK) | PageField);
  207.  
  208.    /* Turn on Z2 caching, if asked for */
  209.  
  210.    if(cache>0)
  211.    {
  212.      PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
  213.      for(i=256; i<1280; i++) *(TempTable+i)=(((8192L*i) & L3MASK) | PageField);
  214.    }
  215.  
  216.    /* Do ROM area, make write protected */ 
  217.  
  218.    PageField = CM_GLOBAL | CM_COPYBACK | WR_PROTECT | PDTRESIDENT;
  219.    for (i=0; i<64; i++)  /* Romsize/pagesize = 512K/8K = 64 pages */
  220.       *(TempTable+i+1984)=(((FASTROMLOC+(8192L*i)) & L3MASK) | PageField);
  221.  
  222.    /* Fold over 7fc0000-7ffffff into F00000-F7ffff so romtags can be found */
  223.  
  224.    PageField = CM_GLOBAL | CM_COPYBACK | WR_PROTECT | PDTRESIDENT;
  225.    for (i=0; i<32; i++) 
  226.       *(TempTable+i+2016)=(((FASTROMLOC+(8192L*i)) & L3MASK) | PageField);
  227.  
  228.    /* Make the area from f80000 to fc0000 mirror at fc0000 - ffffff */
  229.  
  230.    PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
  231.    for (i=0;i<32;i++)
  232.       *(TempTable+i+1920)=(((0x7fc0000L+(8192L*i)) & L3MASK) | PageField);
  233. }
  234.  
  235. /* TableFill is the general purpose MMU table fill algorithm and requires
  236.    considerably more information. The Pointers to the MMU tables must
  237.    point to properly allocated and aligned memory space. */
  238.  
  239. void 
  240. TableFill(MMUTable, MMUTable2, MMUTable3, Z3MMUTable2, Z3MMUTable3, ROMADDR,
  241.           cache2, cache3, MyConfigStruct, numblocks)
  242. ULONG *MMUTable, *MMUTable2, *MMUTable3, *Z3MMUTable2, *Z3MMUTable3,
  243.        ROMADDR, cache2, cache3, numblocks;
  244. struct ConfigureIt *MyConfigStruct;
  245. {
  246.    ULONG PageField;
  247.    int i,j;
  248.         
  249.    /* The MMU address translation tree has been optimized into three memory
  250.       areas for memory defragmentation purposes. The upper level is 128
  251.       32 bit pointers. These must be adjacent, by definition. However,
  252.       the second and third level tables do not. Once allocated on a suitable
  253.       boundary, all 2nd and 3rd level tables are adjacent in two blocks of
  254.       RAM. The same technique is used later for Zorro III MMU tables */
  255.  
  256.     /* Each element of MMUTable[n] points to a 2nd level table representing
  257.        32 Megabytes. We only care about the lowest 16 Meg, so zero out
  258.        all but the first entry */
  259.  
  260.     for (i = 1; i < 128; i++) *(MMUTable+i) = 0L;
  261.  
  262.     *MMUTable = (((ULONG)MMUTable2 & L1MASK) | UDTRESIDENT); /* Point to Level 2 Table */
  263.  
  264.     /* 2nd Level Table initialization for lowest 32 Meg. There are
  265.        128 entries in the 2nd level table, each pointing to a
  266.        third level table which, in this MMU setup, contains the
  267.        translated addresses for each block of memory. */
  268.  
  269.     /* Zero out pointers to 3rd level tables for upper 16 Meg block */
  270.  
  271.     for (i=64; i<128; i++) *(MMUTable2+i)=0L;
  272.  
  273.     /*Set 2nd Level  pointers to 3rd level tables covering lowest 16 Meg. */
  274.  
  275.     for (i=0; i<64; i++)
  276.        *(MMUTable2+i)=(((ULONG)&MMUTable3[i*32] & L2MASK) | UDTRESIDENT);
  277.  
  278.     /* Set up 3rd level Tables for lowest 16 Meg. Each third
  279.        Level table represents 256K. */
  280.  
  281.     /* Since, in this implementation, all third level tables reside adjacent 
  282.        to one another, a total of 2048 8K (2K*8K = 16M) entries exist. The 
  283.        following 'for' loops takes advantage of this fact for table 
  284.        initialization purposes */
  285.  
  286.     /* Do from 0 to just prior to ROM (All non-cacheable)*/
  287.  
  288.     PageField = CM_GLOBAL | CM_INH_SER | PDTRESIDENT;
  289.     for (i=0; i<1984; i++) /*Romaddr/pagesize = 0xf80000/0x2000 = 1984 pages*/
  290.        *(MMUTable3+i) = (((8192L*i) & L3MASK) | PageField);
  291.  
  292.     /* Do ROM area, make write protected */ 
  293.  
  294.     PageField = CM_GLOBAL | CM_COPYBACK | WR_PROTECT | PDTRESIDENT;
  295.     for (i=0; i<64; i++)  /* Romsize/pagesize = 512K/8K = 64 pages */
  296.        *(MMUTable3+i+1984)=(((ROMADDR+(8192L*i)) & L3MASK) | PageField);
  297.  
  298.     /* Turn on Z2 caching, if asked for */
  299.  
  300.     if(cache2>0)
  301.     {
  302.       PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
  303.       for(i=256; i<1280; i++) *(MMUTable3+i)=(((8192L*i) & L3MASK) | PageField);
  304.     }
  305.  
  306.     /* ZorroIII initialization */
  307.  
  308.     if(MyConfigStruct->StartAddr>=Z3STARTADDR) 
  309.     {
  310.       /* Level 1 Table Generation for Zorro III area; Tables are
  311.          built regardless of the Transparent Translation Registers */
  312.    
  313.       /* Assumption: MyConfigStruct->StartAddr is on a 32Meg Boundary 
  314.                      (FindZorro3Start() ensures this). Any Board less 
  315.                      than 32 Meg will generate a 32 MB MMU table for Zorro 
  316.                      III areas */
  317.  
  318.     for(i=0;i<numblocks;i++)
  319.        *(MMUTable+(MyConfigStruct->StartAddr/0x02000000L)+i)=
  320.                 ((((ULONG)Z3MMUTable2+i*0x200L) & L1MASK) | UDTRESIDENT);  
  321.  
  322.     /* Level 2 Tables for Zorro III space */
  323.  
  324.     for (i=0L;i<(128L*numblocks);i++)
  325.     {
  326.       *(Z3MMUTable2+i)=
  327.          (((ULONG)&Z3MMUTable3[i*32] & L2MASK) | UDTRESIDENT);
  328.  
  329.       /* Level 3 Tables for Zorro III space */
  330.  
  331.       PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;        
  332.       if(!cache3) PageField = CM_GLOBAL | CM_INH_SER | PDTRESIDENT;
  333.  
  334.       for (j=0L; j<32L; j++) 
  335.            *(Z3MMUTable3+i*32L+j) = 
  336.              (((8192L*(32L*i+j)+MyConfigStruct->StartAddr) & L3MASK) | PageField);
  337.     }
  338.   }
  339. }
  340.  
  341. /* FindZorro3Start() determines whether or not a Bridgeboard exists and
  342.    and determines upper and lower bounds for MMU tables to cover
  343.    the Zorro III ram and I/O cards. The start address is rounded down to
  344.    the next lowest 32 MB boundary if it is not on one. The end address is
  345.    rounded up to the next higher 32 MB boundary if not on one. The MMU
  346.    tables must be filled in a 32 MB increment, so this is a valid choice */
  347.  
  348. ULONG FindZorro3Start(struct ConfigureIt *MyConfigStruct)
  349. {
  350.   ULONG temp;
  351.   struct ConfigDev *myCD=NULL;
  352.   struct Library *ExpansionBase = NULL;
  353.   struct MemHeader *mem;
  354.  
  355.   MyConfigStruct->StartAddr = Z3ENDADDR;
  356.   MyConfigStruct->EndAddr = 0L;
  357.   MyConfigStruct->BridgeBoard = 0L;
  358.  
  359.   if((ExpansionBase=OpenLibrary("expansion.library",0L))==NULL) 
  360.   {
  361.       MyConfigStruct->StartAddr = 0L;
  362.       return(0L);
  363.   }
  364.  
  365. /* Loop though autoconfigured boards */
  366.  
  367.   while(myCD=FindConfigDev(myCD,-1L,-1L))
  368.   {
  369.      /* Check and mark if Bridgeboard is found */
  370.  
  371.      if(myCD->cd_Rom.er_Manufacturer==0x201 && myCD->cd_Rom.er_Product==1)
  372.         MyConfigStruct->BridgeBoard=1L;
  373.  
  374.      /* Check for a Zorro III board (any type). Z3STARTADDR = 0x10000000 */
  375.  
  376.      if ((ULONG)(myCD->cd_BoardAddr) >= Z3STARTADDR) 
  377.      {
  378.        /* Check for board less than Z3 end address; In case the OS 
  379.           does not store the config items in increasing order,
  380.           or in a random order */
  381.  
  382.        if ((ULONG)(myCD->cd_BoardAddr) < MyConfigStruct->StartAddr)
  383.              MyConfigStruct->StartAddr = (ULONG)(myCD->cd_BoardAddr);
  384.  
  385.        /* I am assuming that when you take a previous board address and
  386.           add its length, you will get the address of the next board,
  387.           therefore, I test with >= rather than > in the following statement: */
  388.  
  389.        if ((ULONG)(myCD->cd_BoardAddr) >= MyConfigStruct->EndAddr)
  390.        {
  391.          /* I am not sure how Slot Size and Board Size relate. I have seen
  392.             a Progressive Zorro III ram card which only had 16 of 64 Meg
  393.             populated. In that case 64K * SlotSize and BoardSize did not
  394.             agree. To be conservative, I will take the larger range of the
  395.             two. This ensures that the area will be covered, although it might
  396.             be a bit much. */
  397.  
  398.          if(65536L*(ULONG)myCD->cd_SlotSize > (ULONG)myCD->cd_BoardSize)
  399.          {    
  400.             MyConfigStruct->EndAddr = 
  401.                 (ULONG)(myCD->cd_BoardAddr) + 
  402.                      65536L*(ULONG)(myCD->cd_SlotSize);
  403.          }
  404.          else /* BoardSize > than 64K * SlotSize */
  405.          {
  406.             MyConfigStruct->EndAddr = 
  407.                 (ULONG)(myCD->cd_BoardAddr) + 
  408.                      (ULONG)(myCD->cd_BoardSize);
  409.          }
  410.        }
  411.      }
  412.   }
  413.  
  414. /* This code double checks the memory lists against my board config sizing
  415.    logic above. Should a ZorroIII memory board not correctly work due to the
  416.    above logic, it should be found via the memory lists and corrected. 
  417.    Zorro III space is defined as anywhere between 0x10000000 and 0xffffffff */
  418.   
  419.   /* Prevent anyone from walking the memory lists while we are using them */
  420.  
  421.   Forbid(); 
  422.  
  423.   /* Get pointer to system memory lists */
  424.  
  425.   mem=(struct MemHeader *)(SysBase->MemList.lh_Head); 
  426.  
  427.   /* Loop until all nodes have been checked */
  428.  
  429.   while (mem->mh_Node.ln_Succ)
  430.   {
  431.     /* Check lower bounds of memory area against the beginning of Zorro III
  432.        space and the lowest Zorro III address detected */
  433.  
  434.     if((ULONG)mem->mh_Lower >= Z3STARTADDR)
  435.     {
  436.       if( (ULONG)mem->mh_Lower <  MyConfigStruct->StartAddr)
  437.       {
  438.          MyConfigStruct->StartAddr = (ULONG)(mem->mh_Lower);
  439.       }
  440.  
  441.       /* Check upper memory list bounds against the largest Z3 board found */
  442.  
  443.       if((ULONG)mem->mh_Upper > MyConfigStruct->EndAddr)
  444.       {
  445.          MyConfigStruct->EndAddr = (ULONG)(mem->mh_Upper);
  446.       }
  447.     }
  448.     
  449.     /* Go to next node in memory list */
  450.  
  451.     mem=(struct MemHeader *)(mem->mh_Node.ln_Succ);
  452.   }
  453.  
  454.   /* We are done, so let system continue */
  455.  
  456.   Permit(); 
  457.  
  458.   /* If StartAddr was never modified, then there is no Zorro III ram or I/O
  459.      in this system and set it to a value other routines will detect */
  460.  
  461.   if(MyConfigStruct->StartAddr == Z3ENDADDR) MyConfigStruct->StartAddr=0L;
  462.   CloseLibrary(ExpansionBase);
  463.  
  464.   /* Now round start and end address to nearest full 32 MB increment */
  465.  
  466.   if(MyConfigStruct->StartAddr >= Z3STARTADDR)
  467.   {
  468.      /* The following code will round StartAddr to the next lowest 32MB boundary
  469.         if it is not already on one. */
  470.   
  471.      MyConfigStruct->StartAddr = MyConfigStruct->StartAddr/0x02000000L;
  472.      MyConfigStruct->StartAddr *= 0x02000000L;
  473.  
  474.      /* We want to round the end address up to the next higher 32 MB boundary
  475.         if it does not end on a 32 MB boundary. */
  476.  
  477.      temp = MyConfigStruct->EndAddr/0x02000000L;
  478.      temp *= 0x02000000L;
  479.      if (temp != MyConfigStruct->EndAddr) MyConfigStruct->EndAddr = temp + 0x02000000L;
  480.   }
  481.   return (0L); 
  482. }
  483.  
  484. /* This replaces the Lattice "stricmp()" function, plus it's a better form
  485.    for my needs here. */
  486.    
  487. static BOOL striequ(s1,s2)
  488. char *s1,*s2;
  489. {
  490.    BOOL aok;
  491.    
  492.    while (*s1 && *s2 && (aok = (*s1++ & 0xdf) == (*s2++ & 0xdf)));
  493.    return (BOOL) (!*s1 && aok);
  494. }
  495.  
  496. /* Page tables and other MMU stuff must be on a page sized boundary, and
  497.    that boundary must be a power of two.  This routine allocates such an
  498.    aligned block of memory. */
  499.  
  500. /* AllocAligned now allocates a 32 byte wall around the the Allocation to
  501.    help protect against memlist tail overwrites and other programs which
  502.    overrun their adjacent memory allocations. The address returned is the 
  503.    'safe' aligned address. 32 bytes before and 32+size bytes past the 
  504.    'safe' address are allocated. */
  505.  
  506. void *AllocAligned(size,bound)
  507. ULONG size;
  508. ULONG bound;
  509. {
  510.    void *mem, *aligned;
  511.    ULONG length;
  512.    
  513.    length=size+bound+WALLSIZE;
  514.    if (!(mem = (void *)AllocMem(length,MEMF_FAST))) return NULL;   
  515.    Forbid();
  516.    aligned = (void *)((((ULONG)mem + bound - 1) & ~(bound - 1))-WALL);
  517.    FreeMem(mem,length);
  518.    mem = (void *)AllocAbs(size+WALLSIZE,aligned);
  519.    Permit();
  520.    mem=(void *)((ULONG)mem+WALL);
  521.    return mem;
  522. }
  523.  
  524. void PatchRom(RomAddr)
  525. ULONG *RomAddr;
  526. {
  527. ULONG i,DStart, *LTemp;
  528. UWORD Test,*Start;
  529.  
  530. LTemp=(ULONG *)(LogRomStart+4);
  531. DStart=(*(LTemp)-LogRomStart)+(ULONG)RomAddr;
  532. Start=(UWORD *)DStart;
  533.  
  534. /* Patch # 1 -  Remove Rom Checksum error branch */
  535.  
  536. for(i=0;i<5000;i++) /* 5000 word limit from Start address for search */
  537. {
  538.   if((Test=*(Start+i))==0x4685)
  539.     if((Test=*(Start+i+1))==0x6600) 
  540.       {
  541.     *(Start+i)=0x7A00; /* Patch out Rom checksum test */
  542.     break;         /* Not d5 -> moveq #0,d5 following branch test then*/
  543.       }                    /* Error check Always passes! */
  544. }
  545.  
  546. /* Patch # 2 - Prevent 040 mTTx registers from being blown away
  547.            by patching in NOPS over offending opcodes */
  548.  
  549. for(i=0;i<25000;i++)    /*Search up to 25K words away from start for patch */
  550. {
  551.   if(*(Start+i)==MOVEC)
  552.   {
  553.     /* Test for 0x4E7B0003 thru 0x4E7B0007 and 0x4E7B0805 thru 0x4E7B0807 
  554.         and change to 0x4E714E71 (Dual NOPs) */
  555.  
  556.     Test  = *(Start+i+1) & 0xFFF;
  557.     if(Test > 2 && Test < 8 || Test > 804 && Test < 808)
  558.       {
  559.         *(Start+i)   = NOP;
  560.         *(Start+i+1) = NOP;
  561.       }
  562.    }
  563.  }
  564. }
  565.  
  566. int main(argc,argv)
  567. int argc;
  568. char *argv[];
  569. {
  570.    ULONG i, cpu, myTC, myTC30, file, cache, FastRom, numblocks;
  571.    ULONG *MMUTable2,*MMUTable3, *ROM32, *MMUTable, *Z3MMUTable2, *Z3MMUTable3;
  572.    ULONG Z3L2size, Z3L3size, *MMU030Table, both, Z3All, rm13, *TempROM;
  573.    ULONG count, MMUOverride, enttx;
  574.  
  575.    struct ConfigureIt MyConfigStruct;
  576.  
  577.    /* If they're just asking for help */
  578.  
  579.    if (argc >= 2 && argv[1][0] == '?') {
  580.       printf("\n\2337mSoftBoot %s\2330m [NOCACHEZ2][KILLROM][NOCATCHROM][ONETHREE]\n",
  581.             PROGRAM_VERSION);
  582.       printf("               [BOTH][SOFTBOOT][NOBUSERRORS][FASTROM]\n");
  583.       printf("               [ENTTX][OVRMMU][NOCACHEZ3][Z3ALL]\n");
  584.       exit2(0L);
  585.    }
  586.  
  587.    enttx=0L;          /* Flag for command line parsing for enttx option */
  588.    rm13=0L;           /* Not loading 1.3 Rom by default */
  589.    both=0L;           /* Not building both 030 and 040 MMU tables by default */
  590.    cache=1L;          /* Turn on Zorro II caching by default */
  591.    Z3cache=1L;        /* Turn on Zorro III caching by default */
  592.    BusErr=0L;         /* Do not turn off the bus error HW by default */
  593.    FastRom=0L;        /* Not performing just a fastrom */
  594.    CatchRom=0L;       /* Do not patch the exception handler for invalid access */
  595.    MMUTable=NULL;     /* Set Pointer to NULL */
  596.    MMU030Table=NULL;  /* Set Pointer to NULL */
  597.    LogRomStart=BASEROMLOC;  /* Logical ROM start address */
  598.    ROM32 = (ULONG *)FASTROMLOC;  /* Physical (relocated) Rom Address */
  599.    MMUOverride=0L;    /* Flag to override existing MMU setup */
  600.    Z3All = 0L;        /* Do not make 040 MMU tables for all of Z3 space */
  601.  
  602.    /* Search for Zorro III start address and length */
  603.  
  604.    (void)FindZorro3Start((struct ConfigureIt *)&MyConfigStruct);
  605.   
  606.    /* Find if there is a bridgeboard and turn off Z2 cache if so */  
  607.  
  608.    if (MyConfigStruct.BridgeBoard) cache=0L;
  609.  
  610.    cpu=GetCPUType();
  611.  
  612.    /* Parse Command line */
  613.  
  614.    if (argc>1) 
  615.    {
  616.      for(i=1;i<argc;i++) 
  617.      {
  618.  
  619.       if ((int)striequ(argv[i],"NOCACHEZ2"))    cache=0L;
  620.       if ((int)striequ(argv[i],"NOCACHEZ3"))    Z3cache=0L;
  621.       if ((int)striequ(argv[i],"ONETHREE"))     {both=1L; rm13=1L; 
  622.                                                  LogRomStart=0x00fc0000L;}
  623.       if ((int)striequ(argv[i],"BOTH"))         both=1L;
  624.       if ((int)striequ(argv[i],"KILLROM"))      {KillRomTags();     
  625.                                                  MyColdReboot();}
  626.       if ((int)striequ(argv[i],"NOBUSERRORS"))  BusErr=1L; 
  627.       if ((int)striequ(argv[i],"FASTROM"))      FastRom=1L;
  628.       if ((int)striequ(argv[i],"NOCATCHROM"))   CatchRom=1L;
  629.       if ((int)striequ(argv[i],"SOFTBOOT"))     {KillRomTags();
  630.                                                  ColdReboot();}
  631.       if ((int)striequ(argv[i],"ENTTX"))        if(cpu==68040L) enttx = 1L;
  632.       if ((int)striequ(argv[i],"OVRMMU"))       MMUOverride=1L;
  633.       if ((int)striequ(argv[i],"Z3ALL"))        Z3All=1L;
  634.       
  635.      }
  636.    }
  637.  
  638.   if(enttx>0L) {ForceTTX(); exit2(0);}
  639.  
  640.  /* Let's Test as much as we can, before we get in too far to back out */
  641.  
  642.    printf("%ld CPU found.\n",cpu);
  643.  
  644.    if (cpu !=68020L && cpu != 68030L && cpu !=68040L)
  645.    {
  646.      printf("SoftBoot Requires a 68030 or 68040 CPU!\n");
  647.      exit2(20L);
  648.    }
  649.  
  650.    if(cpu==68020L) cpu=68030L; /* I'm assuming an '851 */
  651.  
  652.    myTC=0L;
  653.    myTC30=0L;
  654.    if(cpu==68040L) myTC=GetTC040();
  655.    if(cpu==68030L) myTC30=GetTC030();
  656.    if (!MMUOverride && ((cpu == 68040L && myTC) || 
  657.                   (cpu == 68030L && (myTC30 & TCMASK030))))
  658.    {
  659.      printf("FastRom MMU already in operation!\n");
  660.      exit2(0L);
  661.    }
  662.  
  663.    if(cache) printf("Zorro II area will be cached!\n");
  664.  
  665.    if (FastRom)
  666.    {
  667.      both=0L; /* Override Both parameter if Fastrom is called for */
  668.  
  669.      ROM32  = (ULONG *)AllocAligned(ROMSIZE,ROUND030);
  670.      if(!ROM32) 
  671.      {
  672.         printf("FASTROM Memory Allocation Failure! Reboot to defragment!\n"); 
  673.         exit2(20L);
  674.      }
  675.      TempROM=ROM32;
  676.    }
  677.    else /* We're softbooting a new OS */
  678.    {
  679.      TempROM=AllocAbs(ROMSIZE,(APTR)FASTROMLOC);
  680.      if(!TempROM)
  681.      {
  682.        TempROM=AllocAligned(ROMSIZE,0x1000L);
  683.       
  684.     /* Check for No memory or overlap with final destination */ 
  685.  
  686.        if (!TempROM || (((ULONG)TempROM+ROMSIZE+WALL >= FASTROMLOC) &&
  687.                      ((ULONG)TempROM & FASTROMADDRMASK)))
  688.        {
  689.           printf("TempROM Memory Allocation Failure. Reboot to defragment memory!\n"); 
  690.           exit2(20L);
  691.        }
  692.      }
  693.  
  694. /*   The final ROM destination is FASTROMLOC (0x7f80000). At a later point, I 
  695.      will Disable() so I can stomp on this area without crashing someone else.
  696.      So I copy the disk file to 0x7f80000 or a temporary buffer now if 0x7f80000 
  697.      was not directly available, so the read() will not break the Disable() and 
  698.      allow the system to crash and burn by having another task use memory
  699.      I just overwrote. */
  700.  
  701.      if(!rm13) 
  702.      {
  703.        file=open("devs:Kickstart",0L);
  704.        if(file==-1L)
  705.        {
  706.          printf("Error opening devs:Kickstart!\n");
  707.          close(file);
  708.          MyExit(20L,TempROM);
  709.        }
  710.        count=read(file, TempROM, ROMSIZE);
  711.        if(count != ROMSIZE)
  712.        {
  713.          printf("Devs:Kickstart wrong length!\n");
  714.          close(file);
  715.          MyExit(20L,TempROM);
  716.        }
  717.      }
  718.      else
  719.      {
  720.        file=open("devs:Kickstart1.3",0L);
  721.        if(file==-1L)
  722.        {
  723.          printf("Error opening devs:Kickstart1.3!\n");
  724.          close(file);
  725.          MyExit(20L,TempROM);
  726.        }
  727.        count=read(file, TempROM, BONUSSIZE1_3);
  728.        if(count != BONUSSIZE1_3)
  729.        {
  730.          printf("Devs:Kickstart1.3 wrong length!\n");
  731.          close(file);
  732.          MyExit(20L,TempROM);
  733.        }
  734.      }
  735.    }
  736.  
  737.    /* No need to turn caches off if fastromming */
  738.  
  739.    if(!FastRom)CachesOff();
  740.  
  741.    if ((cpu==68030L || both) && !rm13)
  742.    {
  743.      MMU030Table  = (ULONG *)AllocAligned(MMU030TABLESIZE,ROUND030);
  744.  
  745.      if (!MMU030Table || !FastRom && ((ULONG)MMU030Table > Z3STARTADDR))
  746.      { 
  747.        if(FastRom) 
  748.        {
  749.          printf("Out of Memory For MMU tables! Reboot and Retry\n");
  750.        }
  751.        else
  752.        {
  753.          printf("No Memory on A3000|A4000 Motherboard for MMU tables! Reboot to defragment.\n");
  754.        }
  755.        MyExit(20L,TempROM);
  756.      }
  757.    }
  758.    
  759.    if(cpu==68040L || both)
  760.    {
  761.      numblocks=0L;
  762.  
  763.      if(!rm13 && MyConfigStruct.StartAddr>=Z3STARTADDR) 
  764.      {
  765.        printf("Zorro III enabled via MMU at 0x%08lx\n",MyConfigStruct.StartAddr);
  766.  
  767.        /* Count Number of 32 Meg Blocks needed for Zorro III devices */
  768.  
  769.        if (MyConfigStruct.StartAddr >= Z3STARTADDR ) /* if there was Z3 Ram... */
  770.        {
  771.           /* Estimate number of 32 Megabyte RAM areas */
  772.  
  773.           numblocks = (MyConfigStruct.EndAddr - MyConfigStruct.StartAddr)/0x2000000L;
  774.  
  775.           /* Z3ALL flag forces all Zorro III ram to be mapped. This case is
  776.              required if CBM moves start of Zorro III RAM or separates I/O
  777.              space from ram space for 040 mTTx registers. In such a case, the
  778.              old operating system's idea of Zorro III space would not match
  779.              the new operating system, and faulty MMU tables would be built.
  780.              The Z3ALL flag builds MMU tables at great expense in ram, but
  781.              allows the new OS to work until a new softboot is made available.
  782.          
  783.               So, to make the Z3 routines map all of Z3 space, we set
  784.               MyConfig.StartAddr to the beginning of Z3 space and set
  785.               numblocks to cover the entire range.  */
  786.  
  787.           if(Z3All > 0L) 
  788.           {
  789.             numblocks=(Z3ENDADDR - Z3STARTADDR + 1L)/0x02000000L;
  790.             MyConfigStruct.StartAddr=Z3STARTADDR;
  791.           }
  792.         }
  793.       }
  794.  
  795.      Z3L3size=numblocks*Z3L3SIZEPERBLOCK; /*Third level tables' size */
  796.      Z3L2size=numblocks*Z3L2SIZEPERBLOCK;  /*Second Level Tables' size */
  797.        
  798.      NumMemAreas=3L; /* Number of areas to protect via Kickmemlist */
  799.  
  800.      /* Get the memory for the basic 68040 MMU tables. */
  801.  
  802.      if(!rm13)
  803.      {
  804.        MMUTable  = (ULONG *)AllocAligned(TABSIZE,ROUND);
  805.        MMUTable2 = (ULONG *)AllocAligned(TABSIZE,ROUND);
  806.        MMUTable3 = (ULONG *)AllocAligned(LEV3TABSIZE,ROUND);
  807.        Z3MMUTable2 = NULL;
  808.        Z3MMUTable3 = NULL;
  809.  
  810.        /* Allocate Zorro III 2nd and third level tables */
  811.  
  812.        if(MyConfigStruct.StartAddr>=Z3STARTADDR) 
  813.        {
  814.          Z3MMUTable2 =      (ULONG *)AllocAligned(Z3L2size,ROUND);
  815.          Z3MMUTable3 =      (ULONG *)AllocAligned(Z3L3size,ROUND);
  816.  
  817.          /* Update KickMemList Tables for protection of Zorro III tables
  818.             Note areas are protected via one WALL before and after actual
  819.             Area used. */
  820.  
  821.          if(!FastRom)
  822.          {
  823.             MemListArray[6] =  (ULONG)Z3MMUTable2-WALL;
  824.             MemListArray[7] =  Z3L2size+WALLSIZE;
  825.             MemListArray[8] =  (ULONG)Z3MMUTable3-WALL;
  826.             MemListArray[9] =  Z3L3size+WALLSIZE;
  827.             NumMemAreas=5L;   /* Now five memory areas to protect */
  828.          }
  829.        }
  830.  
  831. /* 
  832.           Last safety check that all MMU tables were allocated. If not,
  833.           return memory that was allocated and exit the program.
  834.           For stability, when booting a new OS, the MMU tables must be
  835.           in A3000|A4000 motherboard range, which are constant and
  836.           available through reset. For FastRom, any RAM is OK. 
  837.  */
  838.  
  839.        if (!MMUTable || !MMUTable2 || !MMUTable3 ||
  840.            !FastRom && ((ULONG)MMUTable > Z3STARTADDR) ||  
  841.            !FastRom && ((ULONG)MMUTable2 > Z3STARTADDR) ||
  842.            !FastRom && ((ULONG)MMUTable3 > Z3STARTADDR) ||
  843.            !FastRom && ((ULONG)Z3MMUTable2 > Z3STARTADDR) ||
  844.            !FastRom && ((ULONG)Z3MMUTable3 > Z3STARTADDR) ||
  845.           ((MyConfigStruct.StartAddr>=Z3STARTADDR) && (!Z3MMUTable3 || !Z3MMUTable2)))
  846.        {
  847.          if (both && MMU030Table) WallFreeMem(MMU030Table,MMU030TABLESIZE);
  848.          if (MMUTable)            WallFreeMem(MMUTable,TABSIZE);
  849.          if (MMUTable2)           WallFreeMem(MMUTable2,TABSIZE);
  850.          if (MMUTable3)           WallFreeMem(MMUTable3,LEV3TABSIZE);
  851.          if (Z3MMUTable2)         WallFreeMem(Z3MMUTable2,Z3L2size);
  852.          if (Z3MMUTable3)         WallFreeMem(Z3MMUTable3,Z3L3size);
  853.          printf("No Memory on A3000|A4000 Motherboard for MMU tables! Reboot to defragment.\n");
  854.          MyExit(20L,TempROM);
  855.        }
  856.  
  857.       /* Setup KickMemList via MemListArray - Note Safety wall is included! */
  858.  
  859.        if(!FastRom)
  860.        {    
  861.           MemListArray[0] = (ULONG)MMUTable-WALL;
  862.           MemListArray[1] = TABSIZE+WALLSIZE;
  863.           MemListArray[2] = (ULONG)MMUTable2-WALL;
  864.           MemListArray[3] = TABSIZE+WALLSIZE;
  865.           MemListArray[4] = (ULONG)MMUTable3-WALL;
  866.           MemListArray[5] = LEV3TABSIZE+WALLSIZE;
  867.  
  868.           /* Now fill the MMU tables that we have successfully allocated -
  869.              The final location of the new ROM will always be FASTROMLOC */
  870.  
  871.           TableFill(MMUTable, MMUTable2, MMUTable3, Z3MMUTable2, Z3MMUTable3,
  872.                     FASTROMLOC, cache, Z3cache, 
  873.                     (struct ConfigureIt *)&MyConfigStruct, numblocks);
  874.        }
  875.        else /* Fill MMU tables for FastRom */
  876.        {
  877.          TableFill(MMUTable, MMUTable2, MMUTable3, Z3MMUTable2, Z3MMUTable3,
  878.                    (ULONG)TempROM, cache, Z3cache, 
  879.                    (struct ConfigureIt *)&MyConfigStruct, numblocks);
  880.        } 
  881.      }
  882.      else /* rm13 */
  883.      {
  884.        /* Perform 1.3 MMU magic */
  885.  
  886.        TableFill13(TempROM, cache);
  887.        MMUTable=(ULONG *)0x7fc6000L;
  888.      }
  889.      SRP        = (ULONG)MMUTable;
  890.    }       
  891.    
  892.     if (cpu==68030L || both)
  893.     {
  894.       /* Fill 030 MMU tables */
  895.  
  896.       if(!rm13) /* Note 1.3 bonus builds KS1.3 030 MMU tables */
  897.       {
  898.          for (i=0;i<32;i++) MMU030Table[i]=((PAGESIZE030 * i) + 0x41L);
  899.          for (i=32;i<8160;i++) MMU030Table[i]=((PAGESIZE030 * i) + 1L);
  900.          for (i=8160;i<8192;i++) MMU030Table[i]=((PAGESIZE030 * i) + 0x41L);
  901.          if (cache) for (i=4;i<21;i++) MMU030Table[i]=((PAGESIZE030 * i) + 1L);
  902.          MMU030Table[31] = (ULONG)ROM32 | 5L;
  903.  
  904.          if(!FastRom) /*update kickmemList if we are booting a new OS */
  905.          {
  906.             if (both) /* 040 MMU tables are already loaded into the kickmemlist*/
  907.             {
  908.                MemListArray[NumMemAreas*2]  = (ULONG)MMU030Table-WALL;
  909.                MemListArray[NumMemAreas*2+1]= MMU030TABLESIZE+WALLSIZE;
  910.                NumMemAreas++;
  911.             }
  912.             else /* Only the 030 table needs to be protected */
  913.             {
  914.                MemListArray[0]= (ULONG)MMU030Table-WALL;
  915.                MemListArray[1]= MMU030TABLESIZE+WALLSIZE;
  916.                NumMemAreas=1L;
  917.             }
  918.          }
  919.       }
  920.     }
  921.  
  922.    /* 030 MMU Register values */
  923.  
  924.    TC030 =0x80f0d400L;
  925.    CRP0  =0x7fff0002L;
  926.    CRP1  =(ULONG)(MMU030Table)&~0xfL;
  927.    PhyRomStart= (ULONG)ROM32; /* Wrote into romtag, for its use */
  928.  
  929.   /* Now I have to set up the MMU.  The Supervisor Root Pointer tells the MMU about
  930.      the table I've set up, and the Translation Control register will turn
  931.      the thing on.  */
  932.  
  933.    if(!FastRom)
  934.    {
  935.      /* Softloading a  new OS */
  936.  
  937.      if(rm13)
  938.      { 
  939.        Disable();
  940.        SF_Supervisor();
  941.        CachesOff();
  942.        if((ULONG)TempROM != FASTROMLOC)
  943.                 for(i=0;i<0x20000;i++) *((ULONG *)FASTROMLOC+i) = *(TempROM+i);
  944.        MakeRomTag13();
  945.        CachesOff();
  946.        if(cpu!=68040L)
  947.        {
  948.          JTRom13030();
  949.        }
  950.        else 
  951.        {
  952.          JTRom();
  953.        }
  954.      }
  955.      else /* 2.0 or later */
  956.      {
  957.        PatchRom(TempROM);
  958.        Disable();
  959.        SF_Supervisor();
  960.        MakeRomTag();
  961.        if((ULONG)TempROM!=FASTROMLOC)
  962.                 for(i=0;i<0x20000;i++) *((ULONG *)FASTROMLOC+i) = *(TempROM+i);
  963.        CachesOff();
  964.        JTRom();
  965.      }
  966.    }
  967.    else   /* Fastrom Operation */
  968.    {
  969.      KillRomTags(); /* Blow away rontag headers so they can't ever be found */
  970.      CopyMemQuick((ULONG *)BASEROMLOC,ROM32,ROMSIZE);
  971.      CachesOff();
  972.      SpeedRom();
  973.    }
  974.    exit(0L);
  975. }
  976.